//
// Created by lwj12 on 24-8-15.
//

#ifndef VECTOR_VECTOR_H
#define VECTOR_VECTOR_H
#include <iostream>
#include <vector>
#include<cassert>
#include <algorithm>
using namespace std;

namespace lwj
{
    template<class T, class Ref>
    struct Reverse_iterator
    {
        typedef Reverse_iterator<T, Ref> Self;

        Reverse_iterator(T* it)
                : _it(it)
        {}

        Self& operator++() {return --_it;}
        Self& operator--() {return ++_it;}
        Self operator++(int) {T* tmp = _it; --_it; return tmp;}
        Self operator--(int) {T* tmp = _it; ++_it; return tmp;}
        Self operator-(size_t n) {return Self (_it - n);}
        Self operator+(size_t n) {return Self (_it + n);}

        Ref operator*() {return *_it;}

        bool operator==(const Self& it) {return _it == it._it;}
        bool operator!=(const Self& it) {return _it != it._it;}

        T* _it;
    };

    template<class T>
    class vector
    {
    public:
        typedef Reverse_iterator<T, const T&> const_Reverse_iterator;
        typedef Reverse_iterator<T, T&> Reverse_iterator;
        typedef T* iterator;
        typedef const T* const_iterator;
        iterator begin() {return _start;}
        iterator end() {return _finish;}
        const_iterator begin() const {return _start;}
        const_iterator end() const {return _finish;}Reverse_iterator rbegin() {return Reverse_iterator(_finish - 1);}
        Reverse_iterator rend() {return Reverse_iterator(_start - 1);}
        const_Reverse_iterator rbegin() const {return const_Reverse_iterator(_finish - 1);}
        const_Reverse_iterator rend() const {return const_Reverse_iterator(_start - 1);}

        vector() = default;

        vector(initializer_list<T> it)
        {
            reserve(it.size());
            int i = 0;
            for(auto e : it) push_back(e);
        }

        template<class InputIterator>
        vector(InputIterator first, InputIterator last)
        {
            while(first != last)
            {
                push_back(*first);
                first++;
            }
        }

        vector(size_t n, const T& v = T())
        {
            reserve(n);
            while (n--) push_back(v);
        }
        
        vector(int n, const T& v = T())
        {
            reserve(n);
            while (n--) push_back(v);
        }

        vector(const vector<T>& t)
        {
            reserve(t.capacity());
            for(auto e : t) {push_back(e);}
        }

        ~vector()
        {
            if(_start)
            {
                delete[] _start;
                _start = _finish = _end_of_storage = nullptr;
            }
        }

        size_t capacity() const {return _end_of_storage - _start;}
        size_t size() const {return _finish - _start;}

        void reserve(size_t n)
        {
            if(n > capacity())
            {
                size_t old_size = size();
                T* tmp = new T[n];
                if(_start)
                {
                    //浅拷贝, 不适用自定义类型
                    //memcpy(tmp, _start, size() * sizeof(T));
                    for(size_t i = 0; i < old_size; i++) tmp[i] = _start[i];
                    delete[] _start;
                }
                _start = tmp;
                _finish = _start + old_size;
                _end_of_storage = _start + n;
            }
        }

        iterator insert(iterator pos, const T& t)
        {
            assert(pos >= _start && pos <= _finish);
            if(_finish == _end_of_storage)
            {
                size_t oldpos = pos - _start;
                size_t newCapacity = capacity() == 0 ? 4 : 2 * capacity();
                reserve(newCapacity);
                pos = _start + oldpos;
            }
            iterator end = _finish - 1;
            while (end >= pos)
            {
                *(end + 1) = *end;
                --end;
            }
            *pos = t;
            _finish++;
            return pos;
        }

        void erase(iterator pos)
        {
            assert(pos >= _start && pos < _finish);
            while (pos < _finish)
            {
                *pos = *(pos + 1);
                pos++;
            }
            _finish--;
        }

        void push_back(const T& t) {insert(_finish, t);}
        void pop_back() {earse(_finish - 1);}

        void swap(vector<T>& t)
        {
            std::swap(_start, t._start);
            std::swap(_finish, t._finish);
            std::swap(_end_of_storage, t._end_of_storage);
        }

        vector<T>& operator=(vector<T> t) {swap(t); return *this;}

        T& operator[](size_t n) {assert(n < size()); return _start[n];}

        const T& operator[](size_t n) const { assert(n <size()); return _start[n];}

    private:
        T* _start = nullptr;
        T* _finish = nullptr;
        T* _end_of_storage = nullptr;
    };

    void test() {
        lwj::vector<string> v = {"12345", "1234", "1235", "1245", "1345", "2345"};
       for(auto it = v.rbegin(); it != v.rend(); it++)
        {
           *it = "123";
           cout << *it << ' ';
       }
       cout << endl;
    }
}

#endif//VECTOR_VECTOR_H
